﻿#region Using Statements
using System;
using GameBase.Screens;
using GameBase.Sprites;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using StarFox.Sounds;
#endregion

namespace StarFox.ScreenComponents
{
    /// <summary>
    /// Messages associated to GamePlayScreen (gameplay).
    /// </summary>
    public class GamePlayMessage : ScreenComponent2D
    {
        #region Fields

        SpriteSheet spriteSheet;
        GamePlaySound sound;

        float msgTime;
        float msgAlpha;

        Texture2D msgBkgEffect;
        Rectangle dstRectMsgBkgEffect;

        Texture2D[] dmgEffect = new Texture2D[3];        
        bool[] dmgLevel = new bool[3];

        #endregion

        #region Properties

        /// <summary>
        /// Sets the duration of the message.
        /// </summary>
        public TimeSpan Duration
        {
            private get;
            set;
        }

        #endregion

        #region Screen Transitions

        /// <summary>
        /// Makes the component transition to visible state.
        /// </summary>
        public override void Show()
        {
        }

        /// <summary>
        /// Makes the component transition to hidden state.
        /// </summary>
        public override void Hide()
        {
        }

        #endregion

        #region Constructor

        /// <summary>
        /// Initializes a new instance of this class.
        /// </summary>
        /// <param name="screen">The Screen that this ScreenComponent2D is associated to.</param>
        public GamePlayMessage(Screen screen)
            : base(screen)
        {
            spriteSheet = Game.Content.Load<SpriteSheet>(ContentSettings.GetAsset("MSG_SPRITES"));

            sound = Game.Services.GetService(typeof(GamePlaySound)) as GamePlaySound;
            if (sound == null)
                throw new InvalidOperationException("Service of type StarFoxSound not found");

            msgBkgEffect = Screen.Content.Load<Texture2D>(ContentSettings.GetAsset("GLOW_EFFECT"));

            for (int i = 0; i < 3; i++) { dmgEffect[i] = Screen.Content.Load<Texture2D>(ContentSettings.GetAsset("BROKEN_GLASS_0" + (i + 1).ToString())); }

            dstRectMsgBkgEffect = new Rectangle() { Width = Screen.Width, Height = Screen.Height, Location = Point.Zero };
        }

        #endregion

        #region Cancel

        private void Cancel()
        {
            isDanger = false;
            isWarning = false;
            isPowerUp = false;
            isBombMode = false;

            msgTime = 0.0f;
        }

        #endregion

        #region Collisions

        bool isDanger;
        bool isWarning;

        /// <summary>
        /// Shows asteroid collision effect.
        /// </summary>
        /// <param name="bombMode">true if bomb mode active; false otherwise.</param>
        public void Collision(bool bombMode)
        {
            Cancel();

            if (!bombMode)
            {
                isDanger = true;
                sound.Danger_Collision();
            }
            else
            {
                isWarning = true;
                sound.BombMode_Collision();
            }
        }

        #endregion

        #region Power-Up

        bool isPowerUp;
        PowerUp.PowerUpType powerUpType;

        /// <summary>
        /// Shows power-up effect.
        /// </summary>
        /// <param name="type">The type of the power-up.</param>
        public void PowerUp(PowerUp.PowerUpType type)
        {
            Cancel();

            isPowerUp = true;
            powerUpType = type;

            switch (powerUpType)
            {
                case ScreenComponents.PowerUp.PowerUpType.BOMB:
                    sound.ExtraBomb();
                    break;
                case ScreenComponents.PowerUp.PowerUpType.LIFE:
                    sound.ExtraLife();
                    break;
                default:
                    sound.PowerUp();
                    break;
            }
        }

        #endregion

        #region Bomb Mode

        bool isBombMode;

        /// <summary>
        /// Shows bomb mode activation effect.
        /// </summary>
        public void BombMode()
        {
            Cancel();

            isBombMode = true;
            sound.BombMode_Activation();
        }

        #endregion

        #region Damage

        /// <summary>
        /// Shows damage effect.
        /// </summary>
        /// <param name="health">StarShip's health.</param>
        public void Damage(float health)
        {
            dmgLevel[0] = (health <= 0.30f);
            dmgLevel[1] = (health <= 0.20f);
            dmgLevel[2] = (health <= 0.10f);
        }

        #endregion

        #region Update

        /// <summary>
        /// Called when the ScreenComponent2D needs to be updated.
        /// </summary>
        /// <param name="gameTime">Time elapsed since the last call to this method.</param>
        public override void Update(GameTime gameTime)
        {
            if (Screen.Paused)
                return;

            float timeDelta = (float)(gameTime.ElapsedGameTime.TotalMilliseconds / Duration.TotalMilliseconds);
            msgTime += timeDelta;
            msgTime = MathHelper.Clamp(msgTime, 0.0f, 1.0f);
            if (msgTime == 1.0f) { isDanger = false; isWarning = false; isPowerUp = false; isBombMode = false; msgTime = 0.0f; }
            msgAlpha = 1.0f - (float)Math.Pow(msgTime, 2);
        }

        #endregion

        #region Draw

        /// <summary>
        /// Called when the ScreenComponent2D needs to be drawn.
        /// </summary>
        /// <param name="gameTime">Time elapsed since the last call to this method.</param>
        public override void Draw(GameTime gameTime)
        {
            #region Damage

            for (int i = 0; i < 3; i++)
            {
                if (dmgLevel[i]) { SpriteBatch.Draw(dmgEffect[i], dstRectMsgBkgEffect, Color.Red); }
            }

            #endregion

            Rectangle auxRect;

            #region Collisions

            if (isDanger)
            {
                if (!Screen.Paused)
                {
                    auxRect = spriteSheet.SourceRectangle("DANGER");
                    SpriteBatch.Draw(spriteSheet.Texture, new Vector2(Screen.Width * 0.5f, Screen.Height * 0.2f), auxRect, Color.Red * msgAlpha,
                                     0.0f, new Vector2(auxRect.Width / 2, auxRect.Height / 2), Screen.Scale, SpriteEffects.None, 0);
                }

                SpriteBatch.Draw(msgBkgEffect, dstRectMsgBkgEffect, Color.Red * msgAlpha);
            }

            if (isWarning)
            {
                if (!Screen.Paused)
                {
                    auxRect = spriteSheet.SourceRectangle("WARNING");
                    SpriteBatch.Draw(spriteSheet.Texture, new Vector2(Screen.Width * 0.5f, Screen.Height * 0.2f), auxRect, Color.Aqua * msgAlpha,
                                     0.0f, new Vector2(auxRect.Width / 2, auxRect.Height / 2), Screen.Scale, SpriteEffects.None, 0);
                }

                SpriteBatch.Draw(msgBkgEffect, dstRectMsgBkgEffect, Color.Aqua * msgAlpha);
            }

            #endregion

            #region Power-Up

            if (isPowerUp)
            {
                Color auxColor = Color.Transparent;

                switch (powerUpType)
                {
                    case ScreenComponents.PowerUp.PowerUpType.HEALTH:
                        {
                            auxRect = spriteSheet.SourceRectangle("POWERUP_HEALTH");
                            auxColor = Color.Chartreuse;
                            break;
                        }
                    case ScreenComponents.PowerUp.PowerUpType.BOOST:
                        {
                            auxRect = spriteSheet.SourceRectangle("POWERUP_BOOST");
                            auxColor = Color.Aqua;
                            break;
                        }
                    case ScreenComponents.PowerUp.PowerUpType.FUEL:
                        {
                            auxRect = spriteSheet.SourceRectangle("POWERUP_FUEL");
                            auxColor = Color.Gold;
                            break;
                        }
                    case ScreenComponents.PowerUp.PowerUpType.BOMB:
                        {
                            auxRect = spriteSheet.SourceRectangle("POWERUP_BOMBS");
                            auxColor = Color.Red;
                            break;
                        }
                    case ScreenComponents.PowerUp.PowerUpType.LIFE:
                        {
                            auxRect = spriteSheet.SourceRectangle("POWERUP_LIVES");
                            auxColor = Color.Fuchsia;
                            break;
                        }
                    default:
                        {
                            auxRect = Rectangle.Empty;
                            break;
                        }
                }

                if (!Screen.Paused)
                {
                    SpriteBatch.Draw(spriteSheet.Texture, new Vector2(Screen.Width * 0.5f, Screen.Height * 0.2f), auxRect, auxColor * msgAlpha,
                                     0.0f, new Vector2(auxRect.Width / 2, auxRect.Height / 2), Screen.Scale, SpriteEffects.None, 0);
                }

                SpriteBatch.Draw(msgBkgEffect, dstRectMsgBkgEffect, auxColor * msgAlpha);
            }

            #endregion

            #region Bomb Mode

            if (isBombMode)
            {
                SpriteBatch.Draw(msgBkgEffect, dstRectMsgBkgEffect, Color.Aqua * msgAlpha);
            }

            #endregion
        }

        #endregion
    }
}
